#pragma once

#include "CMultiParentShareableDependencyObject.h"

#include "CMILMatrix.h"
#include "CMILMatrix4x4.h"


class CRenderTarget;
class CPerspectiveTransformer;
class CFrameVectorBuffer;
class CRasterizerPath;

class CProjection :
	public CMultiParentShareableDependencyObject
{

public: 
	static HRESULT Create(CDependencyObject * * ppObject, CREATEPARAMETERS * pCreate);
	virtual XUINT32 GetTypeIndex() const;

	enum XcpFrustumClipPlane
	{
		XcpFrustumClipPlaneTop = 0x1,
		XcpFrustumClipPlaneBottom = 0x2,
		XcpFrustumClipPlaneLeft = 0x4,
		XcpFrustumClipPlaneRight = 0x8,
		XcpFrustumClipPlaneNear = 0x10,
		XcpFrustumClipPlaneFar = 0x20,
		XcpFrustumClipPlaneAll = 0x3F,
	};



protected: 
	CProjection(CCoreServices * pCore);
	virtual ~CProjection();
public: 
	virtual XBOOL Is2DAligned();
	HRESULT NWAddGeometry(struct IPALSurface * pIntermediateSurface, const struct XSIZEF & intermediateSurfaceSize, const struct SharedRenderParams & outerProjectionSharedRP, const struct NWRenderParams & outerProjectionNWRP, struct NWProjectionStorage * pNWProjectionStorage, XBOOL fUpdateEdgesWithoutAdding);
	HRESULT NWBuildProjection(const CFrameVectorBuffer * pTargetVectorBuffer, const struct XSIZEF & intermediateSurfaceSize, const CMILMatrix * pWorldTransform, CRasterizerPath * pQuadPath, struct NWProjectionStorage * pNWProjectionStorage);
	HRESULT GetTransformerCommon(const struct XSIZEF & elementSize, CPerspectiveTransformer * * ppTransformer);
	HRESULT GetContentBounds(const struct XSIZEF & elementSize, const struct XRECTF_RB & quadPadding, struct XRECTF_RB * pContentBounds, XBOOL * pAreAllWValuesPositive);
	virtual HRESULT CloneForTarget(CRenderTarget * pRenderTarget, CProjection * * ppProjection);
	void UpdateProjectionMatrix(const struct XSIZEF & elementSize, CMILMatrix4x4 * pProjectionMatrix);
protected: 
	virtual void Update3DTransform(XFLOAT rWidth, XFLOAT rHeight);
	virtual void Update3DProjection();
	virtual XUINT32 GetFrustumClipMask();
	HRESULT EnsureQuadPath(CRasterizerPath * * ppQuadPath);
private: 
	HRESULT BuildProjectionCommon(const CMILMatrix * pWorldTransform, const struct XSIZEF & elementSize, const struct XRECTF_RB & quadPadding, struct XSIZEF * pTargetVectorBufferSize, const struct XRECTF_WH * pScreenClip, CRasterizerPath * pQuadPath, const struct XRECTF_RB & textureBounds, XBOOL fIsHardwareCached, XBOOL & fClipped, struct XPOINTF4 * pPtsOut, struct XVERTEX25D * pTopLeft, struct XVERTEX25D * pDX, struct XVERTEX25D * pDY, XBOOL * pAreAllWValuesPositive);
	void Create3DQuad(const struct XSIZEF & elementSize, const struct XRECTF_RB & quadPadding, const CMILMatrix * pWorldTransform, const struct XRECTF_RB & textureBounds, struct SDPoint4UV_t * pQuad, CMILMatrix4x4 * pProjectionPipeline);
	HRESULT Clip3DQuad(struct SDPoint4UV_t * pQuad, struct XSIZEF * pTargetVectorBufferSize, const struct XRECTF_WH * pScreenClip, XBOOL fIsHardwareCached, XUINT32 * puClippedPolygonVerticesCount, struct SDPoint4UV_t * pClippedPolygon, XBOOL & fClipped);
	void ProjectToPlane(struct SDPoint4UV_t * pClippedPolygon, XUINT32 uiClippedPolygonVertices, CRasterizerPath * pQuadPath, struct XPOINTF * pScreenSpacePoints, struct XPOINTF4 * pPtsOut, XBOOL * pAreAllWValuesPositive);
	void SetUpTextureInterpolators(struct XPOINTF * pScreenSpacePoints, struct SDPoint4UV_t * pClippedPolygon, XUINT32 uiClippedPolygonVertices, struct XVERTEX25D * pTopLeft, struct XVERTEX25D * pDX, struct XVERTEX25D * pDY, XBOOL * pfIsSingularProjection);
protected: 
	CMILMatrix4x4 m_matTransform3D;  
	CMILMatrix4x4 m_matProjection;
	CMILMatrix m_WorldTransform; 

};